package com.risk.ctrl.credit.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.risk.ctrl.credit.entity.RcpMerchantApiRela;
import com.risk.ctrl.credit.mapper.RcpMerchantApiRelaMapper;
import com.risk.ctrl.credit.service.IRcpMerchantApiRelaService;
import com.risk.ctrl.entity.dto.RcpMerchantDTO;
import com.risk.ctrl.entity.property.ReqProperty;
import com.risk.ctrl.enums.ErrorCodeEnum;
import com.risk.ctrl.exceptions.BusinessException;
import com.risk.ctrl.utils.Md5Utils;
import com.risk.ctrl.utils.StringBulidUtils;
import com.risk.ctrl.utils.ValidateUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.AntPathMatcher;

import java.util.Objects;

/**
 * @Description: 限流表
 * @Author: jeecg-boot
 * @Date:   2025-10-05
 * @Version: V1.0
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class RcpMerchantApiRelaServiceImpl extends ServiceImpl<RcpMerchantApiRelaMapper, RcpMerchantApiRela> implements IRcpMerchantApiRelaService {
    private static final String SIGN_FORMAT = "appkey={appKey}&appsecret={appSecret}&ctime={ctime}";
    private final ReqProperty reqProperty;
    @Override
    public void validate(RcpMerchantDTO rcpMerchantDTO) {
        ValidateUtils.validateObj(rcpMerchantDTO);
        long currentTimeMillis = System.currentTimeMillis();
        if(currentTimeMillis > reqProperty.getLimit().getTime() + rcpMerchantDTO.getTime()){
            throw new BusinessException(ErrorCodeEnum.AUTH_QUERY_TIMEOUT);
        }
        LambdaQueryWrapper<RcpMerchantApiRela> queryWrapper = Wrappers.lambdaQuery(RcpMerchantApiRela.class)
                .eq(RcpMerchantApiRela::getAppKey, rcpMerchantDTO.getAppKey());
        RcpMerchantApiRela rcpMerchantApiRela = this.getOne(queryWrapper);
        if(Objects.isNull(rcpMerchantApiRela)){
            throw new BusinessException(ErrorCodeEnum.USER_NOT_EXIST);
        }
        String sign = getSign(rcpMerchantDTO.getAppKey(), rcpMerchantApiRela.getAppSecret(), rcpMerchantDTO.getTime());
        if(!sign.equals(rcpMerchantDTO.getSign())){
            throw new BusinessException(ErrorCodeEnum.AUTHORITY_FAILED);
        }
        if(Objects.nonNull(rcpMerchantApiRela.getEffDate()) && rcpMerchantApiRela.getEffDate().getTime() > currentTimeMillis){
            throw new BusinessException(ErrorCodeEnum.AUTHORITY_FAILED);
        }
        if(Objects.nonNull(rcpMerchantApiRela.getExpData()) && rcpMerchantApiRela.getExpData().getTime() < currentTimeMillis){
            throw new BusinessException(ErrorCodeEnum.AUTHORITY_FAILED);
        }
        if(!allow(rcpMerchantDTO)){
            return;
        }
        if(Objects.isNull(rcpMerchantApiRela.getUsageCount()) || (Objects.nonNull(rcpMerchantApiRela.getUsedNumber()) && rcpMerchantApiRela.getUsedNumber() >= rcpMerchantApiRela.getUsageCount())){
            throw new BusinessException(ErrorCodeEnum.SEARCHING_NUMBER_OVER_LIMIT);
        }

    }
    private  String getSign(String appKey, String appSecret, Long ctime) {
        return Md5Utils.md52Hex(StringBulidUtils.replaceAllBrace(SIGN_FORMAT, appKey, appSecret, ctime));
    }

    private boolean allow(RcpMerchantDTO rcpMerchantDTO) {
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        return rcpMerchantDTO.getReqProperty().getInclude().stream().anyMatch(path -> antPathMatcher.match(path, rcpMerchantDTO.getUrl()));
    }
    @Override
    public void updateReqNum(RcpMerchantDTO rcpMerchantDTO) {
        if(!allow(rcpMerchantDTO)){
            return;
        }
        LambdaUpdateWrapper<RcpMerchantApiRela> updateWrapper = Wrappers.lambdaUpdate(RcpMerchantApiRela.class)
                .setSql("used_number = used_number + 1")
                .eq(RcpMerchantApiRela::getAppKey, rcpMerchantDTO.getAppKey());
        this.update(updateWrapper);
    }

    public static void main(String[] args) {
        RcpMerchantApiRelaServiceImpl rcpMerchantApiRelaService = new RcpMerchantApiRelaServiceImpl(new ReqProperty());
        long currentTimeMillis = System.currentTimeMillis();
        String sign = rcpMerchantApiRelaService.getSign("appKey", "appSecret", currentTimeMillis);
       log.info("sign:{},time={}", sign, currentTimeMillis);
    }
}
